package com.htjx.mall.commons.models.enums.typeHandlers;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeException;
import org.apache.ibatis.type.TypeHandler;

import com.htjx.mall.commons.models.enums.IEnum;

public abstract class IEnumMybatisHandler implements TypeHandler<IEnum> {

	private Class<IEnum> type;
	private IEnum[] instanceList;
	protected Configuration configuration;

	@SuppressWarnings("unchecked")
	protected IEnumMybatisHandler() {
		this.type = (Class<IEnum>) (((MappedTypes) (getClass().getAnnotations()[0])).value()[0]);
		this.instanceList = type.getEnumConstants();
	}

	public void setConfiguration(Configuration c) {
		this.configuration = c;
	}

	public void setParameter(PreparedStatement ps, int i, IEnum parameter, JdbcType jdbcType) throws SQLException {
		if (parameter == null) {
			if (jdbcType == null) {
				throw new TypeException(
						"JDBC requires that the JdbcType must be specified for all nullable parameters.");
			}
			try {
				ps.setNull(i, jdbcType.TYPE_CODE);
			} catch (SQLException e) {
				throw new TypeException(
						"Error setting null for parameter #"
								+ i
								+ " with JdbcType "
								+ jdbcType
								+ " . "
								+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
								+ "Cause: " + e, e);
			}
		} else {
			ps.setInt(i, parameter.getIndex());
		}
	}

	public IEnum getResult(ResultSet rs, String columnName) throws SQLException {
		Integer value = rs.getInt(columnName);
		if (rs.wasNull()) {
			return null;
		}
		for (IEnum instance : instanceList) {
			if (value == instance.getIndex()) {
				return instance;
			}
		}
		throw new SQLException("can't get instance for class[" + type.getName() + "] with value[" + value + "]");
	}

	public IEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
		Integer value = rs.getInt(columnIndex);
		if (rs.wasNull()) {
			return null;
		}
		for (IEnum instance : instanceList) {
			if (value == instance.getIndex()) {
				return instance;
			}
		}
		throw new SQLException("can't get instance for class[" + type.getName() + "] with value[" + value + "]");
	}

	public IEnum getResult(CallableStatement cs, int columnIndex) throws SQLException {
		Integer value = cs.getInt(columnIndex);
		if (cs.wasNull()) {
			return null;
		}
		for (IEnum instance : instanceList) {
			if (value == instance.getIndex()) {
				return instance;
			}
		}
		throw new SQLException("can't get instance for class[" + type.getName() + "] with value[" + value + "]");
	}

}
